package com.wanhong.springboot.ssm.framework.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.wanhong.springboot.ssm.framework.constant.CommonConstant;
import com.wanhong.springboot.ssm.framework.exception.BizException;
import com.wanhong.springboot.ssm.framework.exception.BizExceptionCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author w_yu
 * @date 2020/11/26 14:00
 * @desc
 */
@Component
@Slf4j
public class JwtUtil {


    @Autowired
    private JwtConstant jwtConstant;


    private static Map<String, Object> header;

    private Algorithm algorithm;

    static {
        header = new HashMap<>();
        header.put("typ", "JWT");
        header.put("alg", "HS256");
    }

    /**
     * 生成jwt
     *
     * @param userContext 用户信息
     * @return
     */
    public String generateToken(UserContext userContext) {
        //私钥及加密算法
        return JWT.create().withHeader(header)
                .withClaim(JwtConstant.USER_ID, userContext.getUserId())
                .withClaim(JwtConstant.USERNAME, userContext.getUsername())
                .withClaim(JwtConstant.NICK_NAME, userContext.getNickName())
                .withExpiresAt(new Date(System.currentTimeMillis() + jwtConstant.expireTime * CommonConstant.LONG_ONE_THOUSAND)).sign(getAlgorithm());
    }

    /**
     * 解密token
     *
     * @param token
     * @return
     */
    public UserContext decodeToken(String token) {
        try {
            JWTVerifier verifier = JWT.require(getAlgorithm()).build();
            DecodedJWT jwt = verifier.verify(token);
            UserContext userContext = new UserContext();
            userContext.setUserId(jwt.getClaim(JwtConstant.USER_ID).asLong());
            userContext.setUsername(jwt.getClaim(JwtConstant.USERNAME).asString());
            userContext.setNickName(jwt.getClaim(JwtConstant.NICK_NAME).asString());
            return userContext;
        } catch (Exception e) {
            throw new BizException(BizExceptionCodeEnum.TOKEN_ILLEGAL);
        }
    }

    /**
     * 刷新token
     *
     * @param token
     * @return
     */
    public String refreshToken(String token) {
        UserContext userContext = decodeToken(token);
        return generateToken(userContext);
    }

    private Algorithm getAlgorithm() {
        if (algorithm == null) {
            algorithm = Algorithm.HMAC256(jwtConstant.tokenSecret);
        }
        return algorithm;
    }

}
